package cn.stylefeng.guns.core;

import cn.hutool.core.img.Img;
import cn.hutool.core.io.FileUtil;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.*;

/**
 * 文件上传工具类（单文件上传、多文件上传）
 */
@Transactional
public class UploadFileUtil {

    /**
     *  图片上传路径
     */
    public static String IMAGES = "E:\\hyTsfpFile\\images\\";

    /**
     * 单图片上传
     * @param file 图片
     * @param deposeFilesDir 上传路径
     * @param isThum 是否生成缩略图
     * @return
     */
    public static Map<String, Object> fileUploadToOne(MultipartFile file, String deposeFilesDir, Boolean isThum) {

        Map<String, Object> res = new HashMap<>();

        // 非空判断
        if (file.isEmpty()) {
            res.put("state", "500");
            res.put("message", "文件为空");
            return res;
        }
        // 获取附件原名(有的浏览器如chrome获取到的是最基本的含 后缀的文件名,如myImage.png)
        // 获取附件原名(有的浏览器如ie获取到的是含整个路径的含后缀的文件名，如C:\\Users\\images\\myImage.png)
        String fileName = file.getOriginalFilename();
        // 如果是获取的含有路径的文件名，那么截取掉多余的，只剩下文件名和后缀名
        int index = fileName.lastIndexOf("\\");
        if (index > 0) {
            fileName = fileName.substring(index + 1);
        }

        Random random = new Random();

        // 当文件有后缀名时
        if (fileName.indexOf(".") >= 0) {
            // split()中放正则表达式; 转义字符"\\."代表 "."
            String[] fileNameSplitArray = fileName.split("\\.");
            // 文件名
            fileName = System.currentTimeMillis() + "" + random.nextInt(100000) + "." + fileNameSplitArray[fileNameSplitArray.length - 1];
        }
        // 当文件无后缀名时(如C盘下的hosts文件就没有后缀名)
        if (fileName.indexOf(".") < 0) {
            // 文件名
            fileName = System.currentTimeMillis() + "" + random.nextInt(100000);
        }

        // 根据文件的全路径名字(含路径、后缀),new一个File对象dest
        File dest = new File(deposeFilesDir + fileName);
        // 如果该文件的上级文件夹不存在，则创建该文件的上级文件夹及其祖辈级文件夹;
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            // 将获取到的附件file,transferTo写入到指定的位置(即:创建dest时，指定的路径)
            file.transferTo(dest);

            String[] fileNameSplitArray = fileName.split("\\.");

            //图片压缩（只压缩jpg格式）
            if(isThum && "jpg".equals(fileNameSplitArray[fileNameSplitArray.length - 1])){
                double bl = 0.5;
                if(file.getSize() < 1024 * 1024 * 0.5){//小于512KB，压缩比率为1
                    bl = 1;
                }else if(file.getSize() < 1024 * 1024 * 1){ //小于1M，压缩比率为0.8
                    bl = 0.8;
                }else if(file.getSize() < 1024 * 1024 * 3){ //小于3M，压缩比率为0.6
                    bl = 0.6;
                }else{ //其他，压缩比率为0.4
                    bl = 0.4;
                }
                String thumFileName = "压缩_" + fileName;
                File thumFile = new File(deposeFilesDir + thumFileName);
                Img.from(FileUtil.file(dest))
                        .setQuality(bl)//压缩比率
                        .write(FileUtil.file(thumFile));

                res.put("thumFileName", thumFileName); //压缩名
                res.put("thumFileSize", thumFile.length()); //压缩大小
            }else{
                res.put("thumFileName", fileName); //压缩名
                res.put("thumFileSize", file.getSize()); //压缩大小
            }

            res.put("state", "200");
            res.put("message", "上传成功");
            res.put("fileName", fileName);
            res.put("fileSize", file.getSize());
            res.put("fileOrgname", file.getOriginalFilename());
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            res.put("state", "500");
            res.put("message", "上传失败");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            res.put("state", "500");
            res.put("message", "上传失败");
        }
        return res;
    }

    /**
     * 多图片上传
     * @param files 图片
     * @param deposeFilesDir 上传路径
     * @param isThum 是否生成缩略图
     * @return
     */
    public static List<Map<String, Object>> fileUploadToMore(MultipartFile[] files, String deposeFilesDir, Boolean isThum) {

        List<Map<String, Object>> resList = new ArrayList<>(); //返回结果，一个文件对应一个map上传结果
        Random random = new Random();

        for (MultipartFile file : files) {

            Map<String, Object> res = new HashMap<>(); //文件上传结果

            // 判断文件是否有内容
            if (file.isEmpty()) {
                res.put("state", "500");
                res.put("message", "文件为空");
                resList.add(res);
                return resList;
            }
            // 获取附件原名(有的浏览器如chrome获取到的是最基本的含 后缀的文件名,如myImage.png)
            // 获取附件原名(有的浏览器如ie获取到的是含整个路径的含后缀的文件名，如C:\\Users\\images\\myImage.png)
            String fileName = file.getOriginalFilename();
            // 如果是获取的含有路径的文件名，那么截取掉多余的，只剩下文件名和后缀名
            if (fileName.indexOf("\\") > 0) {
                int index = fileName.lastIndexOf("\\");
                fileName = fileName.substring(index + 1);
            }

            // 当文件有后缀名时
            if (fileName.indexOf(".") >= 0) {
                // split()中放正则表达式; 转义字符"\\."代表 "."
                String[] fileNameSplitArray = fileName.split("\\.");
                // 文件名
                fileName = System.currentTimeMillis() + "" + random.nextInt(100000) + "." + fileNameSplitArray[fileNameSplitArray.length - 1];
            }
            // 当文件无后缀名时(如C盘下的hosts文件就没有后缀名)
            if (fileName.indexOf(".") < 0) {
                // 文件名
                fileName = System.currentTimeMillis() + "" + random.nextInt(100000) + "";
            }
            // 根据文件的全路径名字(含路径、后缀),new一个File对象dest
            File dest = new File(deposeFilesDir + fileName);
            // 如果pathAll路径不存在，则创建相关该路径涉及的文件夹;
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            try {
                // 将获取到的附件file,transferTo写入到指定的位置(即:创建dest时，指定的路径)
                file.transferTo(dest);

                //图片压缩
                if(isThum){
                    double bl = 0.5;
                    if(file.getSize() < 1024 * 1024 * 0.5){//小于512KB，压缩比率为1
                        bl = 1;
                    }else if(file.getSize() < 1024 * 1024 * 1){ //小于1M，压缩比率为0.8
                        bl = 0.8;
                    }else if(file.getSize() < 1024 * 1024 * 3){ //小于3M，压缩比率为0.6
                        bl = 0.6;
                    }else{ //其他，压缩比率为0.4
                        bl = 0.4;
                    }
                    String thumFileName = "压缩_" + fileName;
                    File thumFile = new File(deposeFilesDir + thumFileName);
                    Img.from(FileUtil.file(dest))
                            .setQuality(bl)//压缩比率
                            .write(FileUtil.file(thumFile));

                    res.put("thumFileName", thumFileName); //压缩名
                    res.put("thumFileSize", thumFile.length()); //压缩大小
                }

                res.put("state", "200");
                res.put("message", "上传成功");
                res.put("fileName", fileName);
                res.put("fileSize", file.getSize());
                res.put("fileOrgname", file.getOriginalFilename());
            } catch (IllegalStateException e) {
                e.printStackTrace();
                res.put("state", "500");
                res.put("message", "上传失败");
            } catch (IOException e) {
                e.printStackTrace();
                res.put("state", "500");
                res.put("message", "上传失败");
            }
            resList.add(res);
        }
        return resList;
    }

    /**
     * 单视频上传
     * @param file 视频
     * @param deposeFilesDir 上传路径
     * @return
     */
    public static Map<String, Object> fileUploadVideoToOne(MultipartFile file, String deposeFilesDir) {

        Map<String, Object> res = new HashMap<>();

        // 非空判断
        if (file.isEmpty()) {
            res.put("state", "500");
            res.put("message", "文件为空");
            return res;
        }
        // 获取附件原名(有的浏览器如chrome获取到的是最基本的含 后缀的文件名,如myImage.png)
        // 获取附件原名(有的浏览器如ie获取到的是含整个路径的含后缀的文件名，如C:\\Users\\images\\myImage.png)
        String fileName = file.getOriginalFilename();
        // 如果是获取的含有路径的文件名，那么截取掉多余的，只剩下文件名和后缀名
        int index = fileName.lastIndexOf("\\");
        if (index > 0) {
            fileName = fileName.substring(index + 1);
        }

        Random random = new Random();

        // 当文件有后缀名时
        if (fileName.indexOf(".") >= 0) {
            // split()中放正则表达式; 转义字符"\\."代表 "."
            String[] fileNameSplitArray = fileName.split("\\.");
            // 文件名
            fileName = System.currentTimeMillis() + "" + random.nextInt(100000) + "." + fileNameSplitArray[fileNameSplitArray.length - 1];
        }
        // 当文件无后缀名时(如C盘下的hosts文件就没有后缀名)
        if (fileName.indexOf(".") < 0) {
            // 文件名
            fileName = System.currentTimeMillis() + "" + random.nextInt(100000);
        }

        // 根据文件的全路径名字(含路径、后缀),new一个File对象dest
        File dest = new File(deposeFilesDir + fileName);
        // 如果该文件的上级文件夹不存在，则创建该文件的上级文件夹及其祖辈级文件夹;
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            // 将获取到的附件file,transferTo写入到指定的位置(即:创建dest时，指定的路径)
            file.transferTo(dest);

            res.put("state", "200");
            res.put("message", "上传成功");
            res.put("fileName", fileName);
            res.put("fileSize", file.getSize());
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            res.put("state", "500");
            res.put("message", "上传失败");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            res.put("state", "500");
            res.put("message", "上传失败");
        }
        return res;
    }

    /**
     * 多视频上传
     * @param files 视频
     * @param deposeFilesDir 上传路径
     * @return
     */
    public static List<Map<String, Object>> fileUploadVideoToMore(MultipartFile[] files, String deposeFilesDir) {

        List<Map<String, Object>> resList = new ArrayList<>(); //返回结果，一个文件对应一个map上传结果
        Random random = new Random();

        for (MultipartFile file : files) {

            Map<String, Object> res = new HashMap<>(); //文件上传结果

            // 判断文件是否有内容
            if (file.isEmpty()) {
                res.put("state", "500");
                res.put("message", "文件为空");
                resList.add(res);
                return resList;
            }
            // 获取附件原名(有的浏览器如chrome获取到的是最基本的含 后缀的文件名,如myImage.png)
            // 获取附件原名(有的浏览器如ie获取到的是含整个路径的含后缀的文件名，如C:\\Users\\images\\myImage.png)
            String fileName = file.getOriginalFilename();
            // 如果是获取的含有路径的文件名，那么截取掉多余的，只剩下文件名和后缀名
            if (fileName.indexOf("\\") > 0) {
                int index = fileName.lastIndexOf("\\");
                fileName = fileName.substring(index + 1);
            }

            // 当文件有后缀名时
            if (fileName.indexOf(".") >= 0) {
                // split()中放正则表达式; 转义字符"\\."代表 "."
                String[] fileNameSplitArray = fileName.split("\\.");
                // 文件名
                fileName = System.currentTimeMillis() + "" + random.nextInt(100000) + "." + fileNameSplitArray[fileNameSplitArray.length - 1];
            }
            // 当文件无后缀名时(如C盘下的hosts文件就没有后缀名)
            if (fileName.indexOf(".") < 0) {
                // 文件名
                fileName = System.currentTimeMillis() + "" + random.nextInt(100000) + "";
            }
            // 根据文件的全路径名字(含路径、后缀),new一个File对象dest
            File dest = new File(deposeFilesDir + fileName);
            // 如果pathAll路径不存在，则创建相关该路径涉及的文件夹;
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            try {
                // 将获取到的附件file,transferTo写入到指定的位置(即:创建dest时，指定的路径)
                file.transferTo(dest);

                res.put("state", "200");
                res.put("message", "上传成功");
                res.put("fileName", fileName);
                res.put("fileSize", file.getSize());
            } catch (IllegalStateException e) {
                e.printStackTrace();
                res.put("state", "500");
                res.put("message", "上传失败");
            } catch (IOException e) {
                e.printStackTrace();
                res.put("state", "500");
                res.put("message", "上传失败");
            }
            resList.add(res);
        }
        return resList;
    }

    /**
     * 单音乐上传
     * @param file 音乐
     * @param deposeFilesDir 上传路径
     * @return
     */
    public static Map<String, Object> fileUploadMusicToOne(MultipartFile file, String deposeFilesDir) {

        Map<String, Object> res = new HashMap<>();

        // 非空判断
        if (file.isEmpty()) {
            res.put("state", "500");
            res.put("message", "文件为空");
            return res;
        }
        // 获取附件原名(有的浏览器如chrome获取到的是最基本的含 后缀的文件名,如myImage.png)
        // 获取附件原名(有的浏览器如ie获取到的是含整个路径的含后缀的文件名，如C:\\Users\\images\\myImage.png)
        String fileName = file.getOriginalFilename();
        // 如果是获取的含有路径的文件名，那么截取掉多余的，只剩下文件名和后缀名
        int index = fileName.lastIndexOf("\\");
        if (index > 0) {
            fileName = fileName.substring(index + 1);
        }

        Random random = new Random();

        // 当文件有后缀名时
        if (fileName.indexOf(".") >= 0) {
            // split()中放正则表达式; 转义字符"\\."代表 "."
            String[] fileNameSplitArray = fileName.split("\\.");
            // 文件名
            fileName = System.currentTimeMillis() + "" + random.nextInt(100000) + "." + fileNameSplitArray[fileNameSplitArray.length - 1];
        }
        // 当文件无后缀名时(如C盘下的hosts文件就没有后缀名)
        if (fileName.indexOf(".") < 0) {
            // 文件名
            fileName = System.currentTimeMillis() + "" + random.nextInt(100000);
        }

        // 根据文件的全路径名字(含路径、后缀),new一个File对象dest
        File dest = new File(deposeFilesDir + fileName);
        // 如果该文件的上级文件夹不存在，则创建该文件的上级文件夹及其祖辈级文件夹;
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {

            // 将获取到的附件file,transferTo写入到指定的位置(即:创建dest时，指定的路径)
            file.transferTo(dest);

            //获取歌曲信息
            byte[] buf = new byte[128];//初始化标签信息的byte数组
            RandomAccessFile raf = new RandomAccessFile(dest, "r");//随机读写方式打开MP3文件
            raf.seek(raf.length() - 128);//移动到文件MP3末尾
            raf.read(buf);//读取标签信息
            raf.close();//关闭文件
            if(buf.length != 128){//数据长度是否合法
                res.put("state", "500");
                res.put("message", "MP3标签信息数据长度不合法");
            }

            if(!"TAG".equalsIgnoreCase(new String(buf,0,3))){//标签头是否存在
                res.put("state", "500");
                res.put("message", "MP3标签信息数据格式不正确");
            }
            String title = new String(buf,3,30,"gbk").trim();//歌曲名称
            String artist = new String(buf,33,30,"gbk").trim();//歌手名字
//            String Album = new String(buf,63,30,"gbk").trim();//专辑名称
//            String Year = new String(buf,93,4,"gbk").trim();//出品年份
//            String Comment = new String(buf,97,28,"gbk").trim();//备注信息

            res.put("state", "200");
            res.put("message", "上传成功");
            res.put("fileName", fileName);
            res.put("fileSize", file.getSize());
            res.put("fileTitle", title);
            res.put("fileArtist", artist);
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            res.put("state", "500");
            res.put("message", "上传失败");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            res.put("state", "500");
            res.put("message", "上传失败");
        }
        return res;
    }

    /**
     * 单文件
     * @param file 文件
     * @param deposeFilesDir 上传路径
     * @return
     */
    public static Map<String, Object> boFileUpload(MultipartFile file, String deposeFilesDir) {

        Map<String, Object> res = new HashMap<>();

        // 非空判断
        if (file.isEmpty()) {
            res.put("state", "500");
            res.put("message", "文件为空");
            return res;
        }
        // 获取附件原名(有的浏览器如chrome获取到的是最基本的含 后缀的文件名,如myImage.png)
        // 获取附件原名(有的浏览器如ie获取到的是含整个路径的含后缀的文件名，如C:\\Users\\images\\myImage.png)
        String fileName = file.getOriginalFilename();
        // 如果是获取的含有路径的文件名，那么截取掉多余的，只剩下文件名和后缀名
        int index = fileName.lastIndexOf("\\");
        if (index > 0) {
            fileName = fileName.substring(index + 1);
        }

        Random random = new Random();

        // 当文件有后缀名时
        if (fileName.indexOf(".") >= 0) {
            // split()中放正则表达式; 转义字符"\\."代表 "."
            String[] fileNameSplitArray = fileName.split("\\.");
            // 文件名
            fileName = System.currentTimeMillis() + "" + random.nextInt(100000) + "." + fileNameSplitArray[fileNameSplitArray.length - 1];
        }
        // 当文件无后缀名时(如C盘下的hosts文件就没有后缀名)
        if (fileName.indexOf(".") < 0) {
            // 文件名
            fileName = System.currentTimeMillis() + "" + random.nextInt(100000);
        }

        // 根据文件的全路径名字(含路径、后缀),new一个File对象dest
        File dest = new File(deposeFilesDir + fileName);
        // 如果该文件的上级文件夹不存在，则创建该文件的上级文件夹及其祖辈级文件夹;
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            // 将获取到的附件file,transferTo写入到指定的位置(即:创建dest时，指定的路径)
            file.transferTo(dest);

            res.put("state", "200");
            res.put("message", "上传成功");
            res.put("fileName", fileName);
            res.put("fileOrgname", file.getOriginalFilename());
            res.put("fileSize", file.getSize());
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            res.put("state", "500");
            res.put("message", "上传失败");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            res.put("state", "500");
            res.put("message", "上传失败");
        }
        return res;
    }

    /**
     * 删除单个文件
     * @param   path    被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteOneFile(String path) {
        boolean flag = false;
        File file = new File(path);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }

    /**
     * 删除多个文件
     * @param   path    被删除文件的文件名数组
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteMoreFile(String[] path) {
        boolean flag = false;
        File file = null;
        for(String pathName: path){
            file = new File(pathName);
            // 路径为文件且不为空则进行删除
            if (file.isFile() && file.exists()) {
                file.delete();
                flag = true;
            }
        }
        return flag;
    }
}
